DMA Communication Terminology

导言

TileXR 的 README 提到:若 UDMA 不可用,通信会平稳降级为 IPC/MTE。这个说法容易让人误以为 UDMA、IPC 和 MTE 是三个可以直接互换的传输引擎,或者一次 UDMA 调用会在失败后自动改写成 MTE 调用。

更准确的理解是:IPC/MTE 是一条组合路径。IPC 负责让本进程看见其他 Rank 的 NPU 内存,MTE 负责真正搬运数据;UDMA 则是另一套带队列、远端内存注册和完成通知的数据搬运后端。TileXR 所谓“自动降级”主要发生在初始化与能力选择阶段,而不是单次传输内部。

一张图建立边界

下面这张图只回答一个问题:UDMA 与 IPC/MTE 分别如何建立地址关系、搬运数据并确认完成?

![TileXR 中 UDMA 与 IPC/MTE 的数据路径](https://pic.shaojiemike.top/shaojiemike/2026/08/f01ea619c23dadf326955890c04f01d7.png){ width=100% }
根据会话内容整理的自绘示意图:蓝色实线是主要数据路径,橙色虚线是 Host 侧初始化或地址准备,紫色虚线是完成与同步。图中选择点是 Kernel 的显式能力判断,不表示 UDMA API 会自动改写为 MTE API。

读图时应注意三点:

  1. IPC 不搬数据。它只导出、交换和打开设备内存句柄,最终形成 peerMems[] 一类可寻址映射。
  2. MTE 才是 IPC 路径上的搬运引擎。数据通常经过 GM、UB 和远端映射 GM。
  3. UDMA 走独立的队列化路径。AICore 提交 WQE,由 UDMA 引擎完成远端访问,再通过 CQ 或 quiet() 确认完成。

先把层级摆正

DMA 与 xDMA

DMA(Direct Memory Access)首先是一种机制:由专用硬件执行数据传输,通用计算单元不必逐字节参与搬运。CPU、Scalar 或 AICore 仍然可能负责初始化、地址计算和命令提交;“Direct”不等于“完全没有软件参与”。

从广义硬件角度,可以画成:

1
2
3
DMA
├── AI Core 内部 DMA 单元:MTE1、MTE2、MTE3
└── 远端或系统 DMA 引擎:UDMA、SDMA、RDMA 等

但在 SHMEM 的项目术语中,经常使用另一种分类:

1
2
3
4
MTE 后端  vs.  xDMA 后端族
├── UDMA
├── SDMA
└── RDMA / RoCE

这里的 xDMA 只是高速 DMA 类引擎的统称,不是 TileXR 中一个名为 xDMA 的具体接口,也不要与其他厂商名为 XDMA 的控制器混为一谈。MTE 广义上属于 DMA 单元,但 SHMEM 为了区分数据路径,会把 MTE 和 xDMA 分开描述。[^shmem-glossary]

UDMA 的命名边界

当前 SHMEM 术语表把 UDMA 展开为 Unified Direct Memory Access,即统一直接内存访问。TileXR 的 README 和 SHMEM_INTEGRATION.md 写成了 “User-space Direct Memory Access”,而集成总结又采用 “Unified Direct Memory Access”。

结合 TileXR 设计文档中的 UB/URMA 语境,本文采用上游 SHMEM 的 Unified Direct Memory Access。其中 “user-space” 可以描述部分控制方式,但不宜作为这里唯一可信的正式全称。

IPC 与 MTE

IPC(Inter-Process Communication)是进程间通信的总称。在 TileXR 中,它不是传统印象里的 CPU 共享内存拷贝,而是 NPU Runtime 提供的设备内存导出与映射机制

MTE(Memory Transfer Engine)是 AI Core 的数据搬运单元:

  • MTE1:主要负责 L1 到 L0 等核内路径;
  • MTE2:负责 GM 到 UB、L1、L0A/L0B 等路径;
  • MTE3:负责 UB 到 GM 的路径。[^ascend-mte]

所以 “IPC/MTE” 中的斜杠不是同义词连接符,而是表示一条组合路径:IPC 建立可寻址关系,MTE 执行实际数据搬运。

IPC/MTE:映射后搬运

TileXR 初始化 IPC 通路时,大致经历以下过程:

  1. 每个 Rank 分配自己的 NPU 通信缓冲区,前部作为同步 Flag 区,后部作为数据区。
  2. 调用 rtIpcSetMemoryName() 导出本 Rank 的设备内存。
  3. 通过 Socket AllGather 交换 PID、SDID 和内存名称。
  4. 调用 rtIpcOpenMemory() 将对端内存映射进本 Rank 的设备地址空间。
  5. 将映射地址写入 CommArgs.peerMems[i]
  6. Kernel 使用 MTE 对这些地址执行搬运,并通过共享 Flag 完成 Rank 间同步。[^tilexr-comm]

一次典型的 Put/Get 可以抽象为:

1
2
Put:本端 GM → MTE2 → 本端 UB → MTE3 → 对端映射 GM
Get:对端映射 GM → MTE2 → 本端 UB → MTE3 → 本端 GM

MTE 指令通常异步执行,需要使用 SetFlag/WaitFlagEnQue/DeQuePipeBarrier 协调 AI Core 内部流水;跨 Rank 的“数据是否已经可以消费”还需要 IPC Flag 等同步协议。

IPC 的角色

IPC 成功只说明对端内存已经可以通过本地地址访问,不表示任何 Payload 已经完成传输。地址可见性、数据搬运完成和接收方消费就绪是三个不同问题。

UDMA:队列化远端访问

TileXR 的 UDMA 控制面大致是:

  1. Rank 0 生成 SHMEM UID,并通过 Socket 交换给所有 Rank。
  2. 初始化 SHMEM,指定 ACLSHMEM_DATA_OP_UDMA
  3. 建立 SQ、RQ、CQ、QP、远端内存注册信息和 Token。
  4. 取得设备侧 ACLSHMEMAIVUDMAInfo 指针。
  5. 设置 udmaInfoPtrExtraFlag::UDMA
  6. Kernel 通过 Put、Get、Atomic 或 Put-Signal 等接口提交 WQE。
  7. 使用 CQ、quiet() 或相应顺序语义等待非阻塞操作完成。[^tilexr-udma-design]

数据面可以抽象为:

1
2
3
4
AICore 生成并提交 WQE
→ SQ / Doorbell
→ UDMA 引擎执行 GM-to-GM 远端访问
→ CQ 或 quiet() 确认完成

某些 UDMA 接口会使用 UB/MTE3 暂存并下发一条 WQE,但这只是控制描述符的下发过程;大块 Payload 仍由 UDMA 引擎搬运,不能据此把 UDMA 路径误判为 MTE Payload 路径。

与 IPC 地址映射不同,SHMEM/UDMA 通常围绕对称或已注册内存、远端 Rank 和访问 Token 组织地址。因此,IPC 的 peerMems[] 地址与 UDMA 的对称内存操作数不能在没有适配层时直接互换。

两条路径的异同

维度 UDMA IPC/MTE
本质 远端 DMA 数据引擎 IPC 地址映射与 MTE 搬运的组合
寻址 对称或注册内存、Peer Rank、Token 本地地址空间中的 peerMems[rank]
数据路径 通常由 UDMA 完成 GM-to-GM 通常通过 MTE2、UB、MTE3 中转
提交机制 WQE、SQ/RQ、Doorbell Ascend C DataCopy/MTE 指令
完成机制 CQ、quiet()、Fence MTE Pipeline Event 加 IPC Flag
远端原子 可提供 Atomic、Signal 等语义 通常另行设计 Flag 或原子同步协议
初始化成本 SHMEM、QP、注册内存和队列状态 导出、交换并打开 IPC 设备内存
适用环境 依赖相应 UDMA 硬件、组网和软件构建 依赖对端内存可通过 IPC/HCCS/SIO 等路径映射

二者的共同点是:

  • 都依赖 Host 侧先完成资源和地址准备;
  • 都由硬件承担主要 Payload 搬运,而不是 CPU 逐字节复制;
  • 都通常具有异步语义,需要显式处理完成、顺序和可见性;
  • 都不能只凭“零拷贝”三个字推断端到端性能。

UDMA 也不保证在任何情况下都更快。同节点、可直接 HCCS 访问的小数据可能更适合 IPC/MTE;UDMA 更适合需要队列化 GM-to-GM、远端原子操作或 UB/URMA 互联的路径。最终选择仍取决于拓扑、数据规模、同步方式和硬件支持。

自动降级的真实边界

TileXR 当前进程模式的初始化顺序可以简化为:

1
2
3
4
5
InitCommMem()       // 先建立 IPC 通路

InitUDMA() // 尝试附加 UDMA 能力

SyncCommArgs()

InitUDMA() 的多个失败分支会记录 Warning,保持 udmaInfoPtr == nullptr,不设置 ExtraFlag::UDMA,然后返回 TILEXR_SUCCESS。这保证了 UDMA 是附加能力,其初始化失败不会破坏已经建立的 IPC/MTE 通路。[^tilexr-init]

但 UDMA-aware Kernel 正确的结构仍然应该是显式分支:

1
2
3
4
5
6
7
if (UDMAEnabled(args)) {
UDMAPutNbi(...);
UDMAQuiet(...);
} else {
CopyByMTE(args.peerMems[target], ...);
NotifyByIpcFlag(...);
}

TileXR 的设计文档也明确说明:当 UDMAEnabled()false 时,由调用方决定走 MTE 还是报错。所以 README 中的 “Automatic fallback” 应理解成初始化级兼容与旧路径保留,而不是以下几种更强语义:

  • 不是某条 UDMA 指令失败后的逐包重试;
  • 不是 UDMAPutNbi() 内部自动改写成 MTE Copy;
  • 不是跨不同地址模型的无条件透明切换;
  • 也不表示所有既有算子都会自动获得 UDMA 加速。

静默返回风险

如果 Kernel 在 UDMA 不可用时只让 UDMA Wrapper 直接返回,却没有执行 MTE Copy 和 Flag 同步,程序可能继续运行,但远端数据并未更新。平稳降级必须同时包含能力判断、等价数据路径和等价同步语义。

当前源码的完成度

以 2026 年 8 月 25 日检查的 TileXR master HEAD 46c58f3 为准,README 中的自动降级更适合作为设计意图,而不是已经完全验证的透明传输层:

  • tilexr_udma.h 使用了 udma_enabledpeer_mem_ptrspeer_flag_ptrs,但当前 CommArgs 的字段是 extraFlagpeerMemsudmaInfoPtr;[^tilexr-wrapper][^tilexr-args]
  • Wrapper 引用的 SHMEM 头文件和函数名与锁定的 SHMEM 子模块接口并不完全一致;
  • InitThread() 明确跳过 UDMA,线程模式继续使用进程内共享内存;
  • 集成测试对 CommArgs 中 UDMA 字段的检查仍保留为 TODO。[^tilexr-test]

这些现象不改变前面的概念关系,但会影响工程判断:当前源码尚不能证明所有 UDMA-aware 算子都已经具备完整、经过验证的 IPC/MTE 等价回退。

常见误解

  1. 把 IPC 当成慢速 CPU 拷贝。TileXR 的 IPC 主要用于设备内存句柄交换与映射,Payload 可以继续由 NPU 的 MTE 搬运。
  2. 把 MTE 排除在 DMA 之外。从硬件分类看,MTE 是 AI Core 的 DMA 单元;只是 SHMEM 在后端分类中常把 MTE 与 xDMA 分开。
  3. 把 xDMA 当成具体引擎。xDMA 是家族名,UDMA 才是这里的具体后端之一。
  4. 把 Direct 理解成完全没有控制开销。UDMA 仍需要 UID、QP、队列、注册内存、WQE 和完成状态。
  5. 把自动降级理解成单次 API 透明替换。TileXR 当前保证的是 UDMA 初始化失败不破坏旧路径;Kernel 仍需显式实现等价分支。

总结

理解这些术语的关键不是背缩写,而是区分四个问题:

  1. 谁建立地址关系?IPC 或 SHMEM 注册内存与 QP 上下文。
  2. 谁搬运 Payload?IPC/MTE 路径中的 MTE,或 UDMA 路径中的 UDMA 引擎。
  3. 谁报告完成?MTE Event、IPC Flag、CQ、quiet() 等同步机制。
  4. 谁选择路径?Host 初始化暴露能力,Kernel 或上层传输封装显式分派。

因此,可以把全文压缩成一句话:DMA 是机制,xDMA 是家族名,UDMA 是具体远端搬运后端,IPC 负责映射,MTE 负责搬运,而 TileXR 的自动降级是“保留并选择旧路径”,不是“同一条 UDMA 指令自动变成 MTE”。

参考资料

[^shmem-glossary]: CANN SHMEM 术语表
[^ascend-mte]: Ascend C Storage Units and DMA Units
[^tilexr-comm]: TileXR tilexr_comm.cpp
[^tilexr-udma-design]: TileXR UDMA 能力扩展设计
[^tilexr-init]: TileXR UDMA 初始化实现
[^tilexr-wrapper]: TileXR tilexr_udma.h
[^tilexr-args]: TileXR comm_args.h
[^tilexr-test]: TileXR UDMA 集成测试

Author

Shaojie Tan

Posted on

2026-08-25

Updated on

2026-08-25

Licensed under